package commons.data;

import commons.Constants;
import commons.ihm.ParametresAffichageCarto;
import commons.drawing.I_Drawable;
import commons.utils.primitive_geom.Segment_d;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import commons.utils.primitive_geom.Point_d;
import commons.utils.primitive_geom.Rect_d;
import commons.utils.UtilsGeom;


public class Zone extends Rect_d implements I_Drawable {

	public enum TypeZone {RECT, ROND}

	public String name;
	public TypeZone typeZone;

	// Zone principale qui englobe toutes les données
	static public Zone zonePrincipale;
	static {
		zonePrincipale = new Zone(Constants.ZONE_PRINCIPALE_NAME, Zone.TypeZone.RECT, 0, 0, 0, 0);
	}

	public boolean isZonePrincipale() {return this == zonePrincipale;}

	public Zone(String name, TypeZone typeZone, double xMin, double yMin, double xMax, double yMax) {
		super(xMin, yMin, xMax, yMax);
		this.name = name;
		this.typeZone = typeZone;
	}

	@Override
	public boolean contientPt_larg(Point_d pt) {
		if (this==Zone.zonePrincipale)
			return true;
		else if (typeZone == TypeZone.RECT)
			return super.contientPt_larg(pt);
		else if (typeZone == TypeZone.ROND)
			return UtilsGeom.ellipseContientPoint_larg(this, pt);
		else assert false;
		return false;
	}

	public boolean equals (Zone zone) {
		return super.equals((Rect_d)zone) && this.typeZone == zone.typeZone;
	}

	//**************************************************************************
	//**************************************************************************

	public void draw(Graphics2D g, ParametresAffichageCarto pac) {
		Shape shape = getShape(pac);
		if (shape==null) return;

		g.setColor(Color.GRAY);
		g.setStroke(pac.getBasicStroke(1.0f));
		g.draw(shape);
	}

	private Shape getShape(ParametresAffichageCarto pac) {
		if (this==Zone.zonePrincipale) return null; // pas la peine de dessiner la zone principale ...

		switch (typeZone) {
			case RECT :
				return new Rectangle2D.Float(pac.x2X(xMin), pac.y2Y(yMax), pac.lg2LG(xMax-xMin), pac.lg2LG(yMax-yMin));
			case ROND :
				return new Ellipse2D.Float(pac.x2X(xMin), pac.y2Y(yMax), pac.lg2LG(xMax-xMin), pac.lg2LG(yMax-yMin));
		}
		return null;
	}

	public double distTo(Point_d pt) {
		double dist = 99999999;
		switch (typeZone) {
			case RECT :
				dist = UtilsGeom.getDistRectPoint(this, pt.x, pt.y);
//				// On prend le min des distance à chacun des 4 segments
//				dist = Math.min(dist, UtilsGeom.getDistancePtSegment(getPt(1), getPt(2), pt));
//				dist = Math.min(dist, UtilsGeom.getDistancePtSegment(getPt(2), getPt(3), pt));
//				dist = Math.min(dist, UtilsGeom.getDistancePtSegment(getPt(3), getPt(4), pt));
//				dist = Math.min(dist, UtilsGeom.getDistancePtSegment(getPt(4), getPt(1), pt));
				break;

			case ROND :
				// On prend |la distance au centre - le rayon|
				// TODO_NO ALGO : ca peut etre une ellipse !! mais le calcul est trop compliqué
				//  car en pratique, les ellipse seront quasiment des ronds
				double rayon = getWidth()/2;
				dist = Math.abs(pt.distTo(getCenter()) - rayon);
				break;
		}
		return dist;
	}

	
	@Override
	public String toString() {
		return getInfoBulle();
	}

	public String getInfoBulle() {
		return name;
	}

	public String getInfoDetaillee() {
		return "Zone : " + name + "\n\n" +
				" Type : " + typeZone + "\n" +
				" X min = " + xMin + "\n" +
				" X max = " + xMax + "\n" +
				" Y min = " + yMin + "\n" +
				" Y max = " + yMax + "\n";
	}


	@Override
	public boolean contientSeg_larg(Segment_d seg) {
		assert(false) : "not yet implemented";
		return false;
	}

	@Override
	public boolean contientSeg_strict(Segment_d seg) {
		assert(false) : "not yet implemented";
		return false;
	}

	@Override
	public Zone getCopy() {
		assert(false) : "not yet implemented";
		return null;
	}

	@Override
	public Point_d getPt(int numPt) {
		assert(false) : "not to be implemented";
		return null;
	}
}
